home *** CD-ROM | disk | FTP | other *** search
- /* Listing 3. TOPDOWN.C - A Top-Down Recursive-Descent Parser */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdarg.h>
- #include "lex.h"
-
- void expression (void);
- void factor (void);
- void mult_expr (void);
- void mult_predicate (void);
- void predicate (void);
- void statement (void);
- void error (char *fmt,...);
-
- #ifdef PTRACE
- static int Rdepth = 0;
- int rdepth(void) {return( Rdepth * 8 );}
- # define trace(name) printf("%*s%s\n", Rdepth++ * 8, "", name)
- # define untrace(name) (--Rdepth)
- #else
- # define trace(name) /* empty */
- # define untrace(name) /* empty */
- #endif
- /*----------------------------------------------------------------------*/
- void statement( void )
- {
- /* statement->WHILE LP expression RP statement WHILE
- * statement->expression SEMI LP SEMI ID NUMBER
- */
-
- trace("statement");
- if( match(WHILE) )
- {
- advance();
-
- if( match(LP) ) advance();
- else error("Inserting missing left parenthesis.");
-
- expression();
-
- if( match(RP) ) advance();
- else error("Inserting missing right parenthesis.");
-
- statement();
- }
- else if( match(LP) || match(SEMI) || match(ID) || match(NUMBER) )
- {
- expression();
-
- if( match(SEMI) ) advance();
- else error("Inserting missing semicolon.");
- }
- else
- error( "while loop or expression expected\n" );
-
- untrace("statement");
- }
- /*----------------------------------------------------------------------*/
- void expression( void )
- {
- /* expression->mult_expr predicate LP ID NUMBER
- * expression->(epsilon) RP SEMI
- */
-
- trace("expression");
-
- if( match(LP) || match(ID) || match(NUMBER) )
- {
- mult_expr();
- predicate();
- }
- else if( match(RP) || match(SEMI) )
- ; /* epsilon */
- else
- error( "expression expected\n" );
-
- untrace("expression");
- }
- /*----------------------------------------------------------------------*/
- void predicate( void )
- {
- /* predicate->PLUS mult_expr predicate PLUS
- * predicate->MINUS mult_expr predicate MINUS
- * predicate->(epsilon) RP SEMI
- */
-
- trace("predicate");
-
- if( match(PLUS) || match(MINUS) )
- {
- advance();
- mult_expr();
- predicate();
- }
- else if( match(RP) || match(SEMI) )
- ; /* epsilon */
- else
- error("operator or statement-terminator expected\n");
-
- untrace("predicate");
- }
- /*----------------------------------------------------------------------*/
- void mult_expr( void )
- {
- /* mult_expr->factor mult_predicate LP ID NUMBER
- */
-
- trace("mult_expr");
-
- if( match(LP) || match(ID) || match(NUMBER) )
- {
- factor();
- mult_predicate();
- }
- else
- error( "expected number identifier or open parenthesis\n" );
-
- untrace("mult_expr");
- }
- /*----------------------------------------------------------------------*/
- void mult_predicate( void )
- {
- /* mult_predicate->STAR factor mult_predicate STAR
- * mult_predicate->SLASH factor mult_predicate SLASH
- * mult_predicate->(epsilon) RP PLUS MINUS SEMI
- */
-
- trace("mult_predicate");
-
- if( match(STAR) || match(SLASH) )
- {
- advance();
- factor();
- mult_predicate();
- }
- else if( match(RP) || match(PLUS) || match(MINUS) || match(SEMI) )
- ; /* epsilon */
- else
- error("operator expected\n");
-
- untrace("mult_predicate");
- }
-
- /*----------------------------------------------------------------------*/
- void factor( void )
- {
- /* factor->NUMBER NUMBER
- * factor->ID ID
- * factor->LP expression RP LP
- */
-
- trace( "factor" );
-
- if( match(NUMBER) || match(ID) )
- advance();
- else if( match(LP) )
- {
- advance();
- expression();
-
- if( match(RP) ) advance();
- else error("Inserting missing right parenthesis.");
- }
-
- untrace( "factor" );
- }
- /*----------------------------------------------------------------------*/
- void error( char *fmt, ... )
- {
- va_list args;
- va_start( args, fmt );
- vfprintf( stderr, fmt, args );
- va_end( args );
- }
- /*----------------------------------------------------------------------*/
- int main()
- {
- statement();
- return 0;
- }